/*
 *  Copyright 2009 David Kuhn <david.s.kuhn at gmail.com>.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package com.google.code.teamtools.client.view;

import java.util.List;

import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.data.BaseTreeLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelIconProvider;
import com.extjs.gxt.ui.client.data.ModelKeyProvider;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.data.TreeLoader;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.TreePanelEvent;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.extjs.gxt.ui.client.mvc.View;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreSorter;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.util.IconHelper;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;
import com.google.code.teamtools.client.AppEvents;
import com.google.code.teamtools.client.RegistryKeys;
import com.google.code.teamtools.client.data.TreeBeanModelReader;
import com.google.code.teamtools.client.i18n.AppTextConstants;
import com.google.code.teamtools.client.model.IResource;
import com.google.code.teamtools.client.model.IResourceOwner;
import com.google.code.teamtools.client.model.TeamMember;
import com.google.code.teamtools.client.service.TeamServiceAsync;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * 
 * @author David Kuhn <david.s.kuhn at gmail.com>
 */
public class TeamHierarchyView extends View
{
	private static final ModelKeyProvider<BeanModel> keyProvider = new ModelKeyProvider<BeanModel>()
    {
        public String getKey(BeanModel model)
        {
            return ((IResource) model.getBean()).getId().toString();
        }
    };
    
    private static final StoreSorter<BeanModel> storeSorter = new StoreSorter<BeanModel>()
    {
        @Override
        public int compare(Store<BeanModel> store, BeanModel m1, BeanModel m2, String property)
        {
            Object o1 = m1.getBean();
            Object o2 = m2.getBean();
            
            boolean m1Resource = o1 instanceof IResource;
            boolean m2Resource = o2 instanceof IResource;

            if (m1Resource && !m2Resource) {
                return -1;
            } else if (!m1Resource && m2Resource) {
                return 1;
            }

            return ((IResource) o1).getName().compareTo(((IResource) o2).getName());
        }
    };
    
    private static final ModelIconProvider<BeanModel> iconProvider = new ModelIconProvider<BeanModel>()
    {
        public AbstractImagePrototype getIcon(BeanModel model)
        {
        	IResource r = model.getBean();
            if (r instanceof TeamMember) {
                // Use stock user image style. 
            	return IconHelper.createStyle("icon-user");
            }
            
            // TODO at some stage we should probably return a default icon...
            return null;
        }
    };
    
    private static final AppTextConstants APP_TEXT =
            (AppTextConstants) Registry.get(RegistryKeys.APP_TEXT);

    /* Pull reference to service out of the registry so we can query the
     * server for team and resource information. */
    private final TeamServiceAsync service =
            (TeamServiceAsync) Registry.get(RegistryKeys.TEAM_SERVICE);

    private TreeStore<BeanModel> store;
    private TreePanel<BeanModel> tree;
    private TreeLoader<BeanModel> loader;

    public TeamHierarchyView(Controller controller)
    {
        super(controller);
    }

    @Override
    protected void initialize()
    {
    }

    protected void initUI()
    {
        // Grab Western content panel from the registry.
        ContentPanel west = (ContentPanel) Registry.get(AppView.WEST_PANEL);

        // Data proxy which will be used to proxy requests to our service.
        RpcProxy<List<IResource>> proxy = new RpcProxy<List<IResource>>()
        {
            @Override
            protected void load(Object loadConfig, AsyncCallback<List<IResource>> callback)
            {
                GWT.log("Fetching resources from server: loadConfig=" + String.valueOf(loadConfig), null);
                
                IResourceOwner owner = null;
                if (loadConfig != null)
                    owner = ((BeanModel) loadConfig).getBean();

                service.getResourceChildren(
                        Cookies.getCookie(""), owner, callback);
            }
        };

        // Tree loader
        loader = new BaseTreeLoader<BeanModel>(proxy, new TreeBeanModelReader())
        {
            @Override
            public boolean hasChildren(BeanModel owner)
            {
                Object o = owner.getBean();
                return o instanceof IResourceOwner;
            }
        };

        // Tree store which will store our team hierarchy
        store = new TreeStore<BeanModel>(loader);
        store.setKeyProvider(keyProvider);
        store.setStoreSorter(storeSorter);
        store.setMonitorChanges(true);

        tree = new TreePanel<BeanModel>(store);
        tree.setStateful(true);
        tree.setDisplayProperty("name");
        tree.setIconProvider(iconProvider);
        tree.sinkEvents(Event.ONDBLCLICK);
        tree.addListener(Events.OnDoubleClick, new Listener<TreePanelEvent<ModelData>>() 
        {
            public void handleEvent(TreePanelEvent<ModelData> tpe) 
            {
        		// TODO maybe we shouldn't allow this to occur for Resource Owners (i.e. Folders).
                AppEvent evt = new AppEvent(AppEvents.Open, tpe.getItem());
                fireEvent(evt);
            }
        });

        // Content panel which will house our tree widget. Also dispatches
        // navigation events when the team panel is activated/expanded.
        ContentPanel teamPanel = new ContentPanel();
        teamPanel.setAnimCollapse(false);
        teamPanel.setHeading(APP_TEXT.teamTreeTitle());
        teamPanel.addListener(Events.Expand, new Listener<ComponentEvent>()
        {
            public void handleEvent(ComponentEvent be)
            {
                Dispatcher.get().dispatch(AppEvents.NavTeam);
            }
        });

        teamPanel.add(tree);
        west.add(teamPanel);
    }

    protected void handleEvent(AppEvent event)
    {
        if (event.getType() == AppEvents.Init) {
            initUI();
        }
    }
}
